package persistence;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import model.Factura;
import model.FacturaDetalle;
import model.Producto;

public class FacturaMapper implements DataMapper<Factura>{
	
	private ProductoMapper productoMapper;
	private static FacturaMapper instance = null;

	private FacturaMapper() {}
	
	public static FacturaMapper getInstance() {
		if(instance == null) {
			instance = new FacturaMapper();
		}
		
		return instance;
	}
	@Override
	public boolean insertar(Factura factura) {
		boolean result = false;
		Connection connection = PoolConnection.getPoolConnection().getConnection();
		
		try{
			String query = "insert into factura (monto) values (?)";
			PreparedStatement ps = null;
			ps = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
			ps.setFloat(1, factura.getMonto());
			ps.execute();
			
			ResultSet rs = ps.getGeneratedKeys();
			int facturaId = -1;
            if(rs.next()) {
                facturaId = rs.getInt(1);
                factura.setFacturaId(facturaId);
            }
			
			for(FacturaDetalle detalle: factura.getDetalles()) {
				insertarDetallesFactura(connection, facturaId, detalle);
				ProductoMapper.getInstance().actualizarStock(detalle.getProducto(), detalle.getCantidad());
			}
			
			PoolConnection.getPoolConnection().releaseConnection(connection);
			result = true;
		} catch (SQLException e) {
			System.out.println("Mensaje Error al Insertar Factura: " + e.getMessage());
			System.out.println("Stack Trace al Insertar Factura: " + e.getStackTrace());
			PoolConnection.getPoolConnection().releaseConnection(connection);
		}
		return result;
	}

	private void insertarDetallesFactura(Connection connection, long facturaId, FacturaDetalle facturaDetalle) throws SQLException {
		String query = "INSERT INTO factura_detalle (factura_id, producto_id, cantidad, precio_unitario) values(?,?,?,?)";
		PreparedStatement ps = connection.prepareStatement(query);
		ps.setLong(1, facturaId);
		ps.setLong(2, facturaDetalle.getProducto().getProductoId());
		ps.setInt(3, facturaDetalle.getCantidad());
		ps.setFloat(4, facturaDetalle.getPrecioUnitario());
		ps.execute();
		
	}
		
	@Override
	public boolean modificar(Factura instancia) {
		return false;
	}

	@Override
	public boolean eliminar(Factura instancia) {
		return false;
	}

	@Override
	public Factura buscar(Long facturaId) {
		Factura factura = null;
		Connection connection = PoolConnection.getPoolConnection().getConnection();
		
		try{
			String query = "select * from factura where factura_id = ?";
			PreparedStatement ps = connection.prepareStatement(query);
			ps.setLong(1, facturaId);
			ResultSet result = ps.executeQuery();
			
			if(result.next()) {
				factura = new Factura(result.getInt("factura_id"), result.getFloat("monto"), result.getDate("fecha"));
				List<FacturaDetalle> detalles = buscarDetallesFactura(connection, facturaId);
				factura.setDetalles(detalles);
			}
			
			PoolConnection.getPoolConnection().releaseConnection(connection);			
		} catch (SQLException e) {
			System.out.println("Mensaje Error al buscar Factura: " + e.getMessage());
			System.out.println("Stack Trace al buscar Factura: " + e.getStackTrace());
			PoolConnection.getPoolConnection().releaseConnection(connection);
		}
		return factura;
	}

	@Override
	public List<Factura> buscarTodos() {
		List <Factura> facturas = new ArrayList<Factura>();
		Connection connection = PoolConnection.getPoolConnection().getConnection();
		
		try {
			String query = "select * from factura";
			PreparedStatement ps = connection.prepareStatement(query);
			
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				Factura factura = new Factura(rs.getInt("factura_id"), rs.getFloat("monto"), rs.getDate("fecha"));
				List<FacturaDetalle> detalles = buscarDetallesFactura(connection, factura.getFacturaId());
				factura.setDetalles(detalles);
				facturas.add(factura);
			}
			
			PoolConnection.getPoolConnection().releaseConnection(connection);			
		} catch (SQLException e) {
			System.out.println("Mensaje Error Buscar todas las Facturas: " + e.getMessage());
			System.out.println("Stack Trace al Buscar todas las Facturas: " + e.getStackTrace());
			PoolConnection.getPoolConnection().releaseConnection(connection);
		}
		
		return facturas;
	}
		
	private List<FacturaDetalle> buscarDetallesFactura(Connection connection, long facturaId){
		List<FacturaDetalle> facturaDetalles = new ArrayList<FacturaDetalle>();
		
		try {
			String query = "select * from factura_detalle where factura_id = ?";
			PreparedStatement ps = connection.prepareStatement(query);
			ps.setLong(1, facturaId);
			
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				Producto p = productoMapper.buscarProducto(rs.getLong("producto_id"));
				FacturaDetalle fd = new FacturaDetalle(p, rs.getInt("cantidad"), rs.getInt("precio_unitario"));
				facturaDetalles.add(fd);
			}
			
			PoolConnection.getPoolConnection().releaseConnection(connection);			
		} catch (SQLException e) {
			System.out.println("Mensaje Error al buscar Detalles de Factura: " + e.getMessage());
			System.out.println("Stack Trace al buscar Detalles de Factura: " + e.getStackTrace());
			PoolConnection.getPoolConnection().releaseConnection(connection);
		}
		
		return facturaDetalles;
	}
	

}
